package com.strawcom.charmring.bluetooth;

import android.annotation.TargetApi;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Context;
import android.os.Build;
import com.strawcom.charmring.C;
import com.strawcom.charmring.util.ConvertHelper;
import com.strawcom.charmring.util.LogUtil;

import java.io.File;
import java.util.Arrays;
import java.util.UUID;

/**
 * charmring戒指交互控制器<br>
 * 负责处理APP与设备的消息交互逻辑
 * 
 * @author WangPeng
 */
public class RingBleController {
	/** 订阅 */
	public static final UUID CHARACTERISTIC_CLIENT_NOTIFICATION = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
	/** 设备电池服务 */
	public static final UUID SERVICE_BATTERY = UUID.fromString("0000180f-0000-1000-8000-00805f9b34fb");
	/** 设备电池特征值 */
	public static final UUID CHARACTERISTIC_BATTERY = UUID.fromString("00002a19-0000-1000-8000-00805f9b34fb");
	/** 设备消息交互服务 */
	public static final UUID SERVICE_MESSAGE = UUID.fromString("000056EF-0000-1000-8000-00805F9B34FB");
	/** 消息发送特征值 */
	public static final UUID CHARACTERISTIC_SEND = UUID.fromString("000034E1-0000-1000-8000-00805F9B34FB");
	/** 消息接收特征值 */
	public static final UUID CHARACTERISTIC_RECEIVE = UUID.fromString("000034E2-0000-1000-8000-00805F9B34FB");
	/** 发送消息：关闭设备闪灯 */
	public static final byte[] VALUE_CALL_REMIND_CLOSE = { 0x01, 0x00 };
	/** 发送消息：打开设备闪灯 */
	public static final byte[] VALUE_CALL_REMIND_OPEN = { 0x01, 0x01 };
	/** 发送消息：设备闪灯时长 */
	public static final byte[] VALUE_CALL_REMIND_LIGHT_TIME = { 0x01, 0x02, 0x00 };
	// Value motion detection threshold configuration
	public static final byte[] VALUE_MOTION_THRESHOLD_SENSITIVE = { 0x04, 0x1e, 0x02 };
	public static final byte[] VALUE_MOTION_THRESHOLD_SLOW = { 0x04, 0x46, 0x03 };
	/** 发送消息：用于APP通知SmartRing 清除全部运动数据 */
	public static final byte[] VALUE_RESET_RECORDS = { 0x06 };
	/**
	 * 发送消息：用于APP校正SmartRing中间的时间，便于其在运动报告上打正确的时戳 <br>
	 * <b>第二位至第五位表示当前时间距离2000年1月1日零点的秒数<b>
	 */
	public static final byte[] VALUE_SET_TIMESTAMP = { 0x07, 0x00, 0x00, 0x00, 0x00 };
	/**
	 * 消息：用于APP 通知SmartRing立即上报运动数据<br>
	 * <b>0x00 表示APP需要获取所有运动数据，包括没计满1分钟的临时运动数据<br>
	 * 0x01 表示APP不需要没计满1分钟的临时运动数据<b>
	 */
	public static final byte[] VALUE_GET_REPORTS_ALL = { 0x09, 0x00 };
	/**
	 * 消息：用于APP 通知SmartRing立即上报运动数据<br>
	 * <b>0x00 表示APP需要获取所有运动数据，包括没计满1分钟的临时运动数据<br>
	 * 0x01 表示APP不需要没计满1分钟的临时运动数据<b>
	 */
	public static final byte[] VALUE_GET_REPORTS_MIN = { 0x09, 0x01 };

	/**
	 * 消息：基本配置 <br>
	 * 来电提醒功能开关 <b>0x00 来电提醒功能关闭 0x01 来电提醒功能开启</b><br>
	 * 来电提醒灯闪时长（秒）<b>60</b><br>
	 * 紧急告警功能开关 <b>0x00 紧急告警功能关闭 0x01 紧急告警功能开启</b><br>
	 * 防丢提醒功能开关 <b>0x00 防丢提醒功能关闭 0x01 防丢提醒功能开启 </b><br>
	 * 防丢提醒灯闪时长（秒） <b>1~60</b><br>
	 * 防丢提醒延迟时长（秒） <b>0~10</b><br>
	 */
	public static final byte[] VALUE_BASIC_SETTINGS = { 0x0a, 0x01, 0x1e, 0x01, 0x01, 0x1e, 0x0a };

	/** 设备上报：KEEP ALIVE 心跳包 */
	public static final byte MESSAGE_KEEP_ALIVE = 0x02;
	/** 设备上报：记步信息 */
	@Deprecated
	public static final byte MESSAGE_STEP_GAUGE = 0x03;
	/** 设备上报：设备晃动猛烈度溢出设定阀值 */
	public static final byte MESSAGE_MOTION_THRESHOLD = 0x05;
	/**
	 * 戒指中会根据内存、Flash存储情况，蓝牙信号情况来决定何时向APP上报运动数据。<br>
	 * 当戒指中用于缓存运动数据的空间被占据达到一定门限的时候，戒指会发送REPORT_SPORTS指令<br>
	 */
	public static final byte MESSAGE_REPORT_SPORTS = 0x08;

	/** 2000年1月1号对应的秒数 */
	public static final long offsetTime = 946656000; // final ; do not changed !

	public RingBleController(OnRingMessageReceivedListener messagelistener, OnRingUpgradeStepChangedListener upgradelistener) {
		if (messagelistener == null || upgradelistener == null) throw new IllegalArgumentException("empty listener");

		this.messageListener = messagelistener;
		this.upgradeListener = upgradelistener;
	}

	private OnRingMessageReceivedListener messageListener;

	public interface OnRingMessageReceivedListener {
		/** 设备上报阀值溢出消息 */
		void triggerMotionThreshold();

		/** 设备上报记步消息 */
		void stepGauge(String address, boolean hasMore, int t2000ToCurrent, int exerciseMode, short duration, short step);

		/** 设备上报心跳消息 */
		void keepAlive(String address);
	}

	public void dealRingMessage(String address, byte[] message) {
		if (message == null || message.length < 1) {
			LogUtil.e("empty ring ble message .");
			return;
		}

		switch (message[0]) {
		/* 心跳消息 */
		case MESSAGE_KEEP_ALIVE:
			messageListener.keepAlive(address);
			break;
		/* 记步消息上报：原本使用0x03接口，目前已经废止 */
		case MESSAGE_STEP_GAUGE:
			break;
		/* 新的记步消息 */
		case MESSAGE_REPORT_SPORTS:
			LogUtil.e("dealRingMessage STEP_GAUGE:" +message[0]+","+ message[1] + "," + message[2] + "," + message[3] + "," + message[4] + ","
					+ message[5] + "," + message[6] + "," + message[7] + "," + message[8] + "," + message[9] );
			boolean hasMore = message[1] == 1; // 0x00 表示无记录 ; 0x01 表示还有记录
			int t2000ToCurrent = ConvertHelper.byteArray2Integer(Arrays.copyOfRange(message, 2, 6), true);
			
			short modeAndDuration =ConvertHelper.byteArray2Short(Arrays.copyOfRange(message, 6, 8), true);
			int exerciseMode = (modeAndDuration & 0x000f);
			short duration = (short) (modeAndDuration >> 4 & 0x0fff);
			short step = ConvertHelper.byteArray2Short(Arrays.copyOfRange(message, 8, 10), true);
			LogUtil.e("dealRingMessage STEP_GAUGE hasMore:" + hasMore + ",t2000ToCurrent:" + t2000ToCurrent + ",exerciseMode:"
					+ exerciseMode + ",duration:" + duration + ",step:" + step);
			messageListener.stepGauge(address, hasMore, t2000ToCurrent, exerciseMode, duration, step);
			break;
		/* 晃动程度溢出设定阀值消息 */
		case MESSAGE_MOTION_THRESHOLD:
			messageListener.triggerMotionThreshold();
			break;
		default:
			LogUtil.e("dealRingMessage 未处理订阅类型");
			break;
		}
	}

	public static String bytesToHex(byte[] bytes) {
		if (bytes == null) {
			return "";
		}
		final char[] hexArray = "0123456789ABCDEF".toCharArray();
		char[] hexChars = new char[bytes.length * 2];
		for (int j = 0; j < bytes.length; j++) {
			int v = bytes[j] & 0xFF;
			hexChars[j * 2] = hexArray[v >>> 4];
			hexChars[j * 2 + 1] = hexArray[v & 0x0F];
		}
		return new String(hexChars);
	}

	/*
	 * ********** 设备升级逻辑 *************
	 */

	public static File obtainBleUpdateFile(Context context) {

		System.out.println(com.dialog.suota.data.File.filesDir);
		return new File(com.dialog.suota.data.File.filesDir, C.app.ble_ring_update);
	}

	private static int obtainBleUpdateStep(UUID characteristic) {
		if (CHARACTERISTIC_1_SPOTA_MEM_DEV.equals(characteristic)) {
			return UPGRADE_1;
		}
		else if (CHARACTERISTIC_2_SPOTA_GPIO_MAP.equals(characteristic)) {
			return UPGRADE_2;
		}
		else if (CHARACTERISTIC_3_SPOTA_MEM_INFO.equals(characteristic)) {
			return UPGRADE_3;
		}
		else if (CHARACTERISTIC_4_SPOTA_PATCH_LEN.equals(characteristic)) {
			return UPGRADE_4;
		}
		else if (CHARACTERISTIC_5_SPOTA_PATCH_DATA.equals(characteristic)) {
			return UPGRADE_5;
		}
		else if (CHARACTERISTIC_6_SPOTA_SERV_STATUS.equals(characteristic)) {
			return UPGRADE_6;
		}
		else {
			return UPGRADE_UNKOWN;
		}
	}

	public static final int UPGRADE_ERROR = -1;
	public static final int UPGRADE_UNKOWN = 0;
	public static final int UPGRADE_1 = 1;
	public static final int UPGRADE_2 = 2;
	public static final int UPGRADE_3 = 3;
	public static final int UPGRADE_4 = 4;
	public static final int UPGRADE_5 = 5;
	public static final int UPGRADE_6 = 6;
	public static final int UPGRADE_7 = 7;
	// Service
	public static final UUID SERVICE_UPGRADE = UUID.fromString("0000fef5-0000-1000-8000-00805F9B34FB");
	// Characteristic
	public static final UUID CHARACTERISTIC_1_SPOTA_MEM_DEV = UUID.fromString("8082CAA8-41A6-4021-91C6-56F9B954CC34");
	public static final UUID CHARACTERISTIC_2_SPOTA_GPIO_MAP = UUID.fromString("724249F0-5EC3-4B5F-8804-42345AF08651");
	public static final UUID CHARACTERISTIC_3_SPOTA_MEM_INFO = UUID.fromString("6C53DB25-47A1-45FE-A022-7C92FB334FD4");
	public static final UUID CHARACTERISTIC_4_SPOTA_PATCH_LEN = UUID.fromString("9D84B9A3-000C-49D8-9183-855B673FDA31");
	public static final UUID CHARACTERISTIC_5_SPOTA_PATCH_DATA = UUID.fromString("457871E8-D516-4CA1-9116-57D0B17B9CB2");
	public static final UUID CHARACTERISTIC_6_SPOTA_SERV_STATUS = UUID.fromString("5F78DF94-798C-46F5-990A-B3EB6A065C88");
	// Value
	public static final byte[] VALUE_1_SPOTA_MEM_DEV = { 0x00, 0x00, 0x00, 0x13 };
	public static final byte[] VALUE_2_SPOTA_GPIO_MAP = { 0x00, 0x03, 0x06, 0x05 };

	@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) public void dealRingUpgrade(String address, BluetoothGattCharacteristic characteristic) {
		if (characteristic == null || characteristic.getUuid() == null) {
			LogUtil.e("RingBleController dealRingUpgrade() empty ring ble characteristic .");
			return;
		}
		int upgradeStep = obtainBleUpdateStep(characteristic.getUuid());
		LogUtil.d("RingBleController dealRingUpgrade() step ." + upgradeStep);
		upgradeListener.stepChanged(address, upgradeStep);
	}

	private OnRingUpgradeStepChangedListener upgradeListener;

	public interface OnRingUpgradeStepChangedListener {
		void stepChanged(String address, int step);
	}
}
